package com.itlong.cloud.controller.pass;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.itlong.cloud.POJO.DTO.app.AppCallLiftDTO;
import com.itlong.cloud.POJO.DTO.app.AppCallLiftSaveDTO;
import com.itlong.cloud.POJO.DTO.app.AppUploadRecordJsonDTO;
import com.itlong.cloud.POJO.DTO.app.property.app.PropertyAppDeviceGroupInfoDTO;
import com.itlong.cloud.POJO.DTO.app.property.app.PropertyAppDeviceInfoDTO;
import com.itlong.cloud.POJO.DTO.property.IotCloudEntranceStateDTO;
import com.itlong.cloud.POJO.DTO.property.IotCloudIntercomStateDTO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.app.*;
import com.itlong.cloud.POJO.VO.property.AppCloudElevatorRunState;
import com.itlong.cloud.POJO.VO.property.CloudElevatorVO;
import com.itlong.cloud.POJO.VO.property.PropertyUserCacheVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.abstracts.BaseController;
import com.itlong.cloud.common.network.ITCPServiceClient;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.controller.home.PropertyAppHouseholdCheckController;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.enumerate.ecode.AppErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.ErrorCode;
import com.itlong.cloud.enumerate.ecode_en.AppErrorCodeEnumEN;
import com.itlong.cloud.enumerate.ecode_en.BaseErrorCodeEnumEN;
import com.itlong.cloud.equip.app.IAppDevicePassRecordServiceClient;
import com.itlong.cloud.equip.app.IAppDeviceServiceClient;
import com.itlong.cloud.equip.commons.ICloudEntranceServiceClient;
import com.itlong.cloud.equip.property.ICloudIntercomServiceClient;
import com.itlong.cloud.iottp.IIotServerServiceClient;
import com.itlong.cloud.project.app.IAppProjectServiceClient;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.user.app.IAppHomeServiceClient;
import com.itlong.cloud.user.app.IAppUserInfoCacheServiceClient;
import com.itlong.cloud.user.propertyapp.IPropertyAppDeviceInfoServiceClient;
import com.itlong.cloud.user.propertyapp.IPropertyAppUserInfoServiceClient;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <desc>
 *      物业APP通行版块控制器
 * </desc>
 *
 * @create 2020/01/02
 */
@RestController
@RequestMapping("/pass")
@RefreshScope
public class PropertyAppPassController extends BaseController {

    private static final Logger LOG = LoggerFactory.getLogger(PropertyAppPassController.class);

    @Value("${"+ PlatformConstants.PROPERTY_APP_USER_TOKEN_KEY +"}")
    private String propertyAppUserTokenKey;

    @Autowired
    private RedisService redisService;

    @Autowired
    IPropertyAppUserInfoServiceClient iPropertyAppUserInfoServiceClient;

    @Autowired
    ICloudEntranceServiceClient iCloudEntranceServiceClient;

    @Autowired
    IIotServerServiceClient iIotServerServiceClient;

    @Autowired
    IAppDeviceServiceClient iAppDeviceServiceClient;

    @Autowired
    IAppHomeServiceClient iAppHomeServiceClient;

    @Autowired
    ICloudIntercomServiceClient iCloudIntercomServiceClient;

    @Autowired
    ITCPServiceClient itcpServiceClient;

    @Autowired
    IPropertyAppDeviceInfoServiceClient iPropertyAppDeviceInfoServiceClient;

    @Autowired
    private IAppDevicePassRecordServiceClient iAppDevicePassRecordServiceClient;

    @Autowired
    IAppProjectServiceClient iAppProjectServiceClient;

    @Autowired
    IAppUserInfoCacheServiceClient userCache;

    /**
     * <desc>
     *      物业APP获取物业用户二维码
     * </desc>
     *
     * @param token 用户token
     * @param projectId 项目id
     * @author Juguang.S
     * @createDate 2020/01/02
     */
    @RequestMapping(path = "/getQRcode",method = RequestMethod.POST)
    @ResponseBody
    public Object getQRcode(String token,String projectId){
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            if (StringUtils.isBlank(projectId) || StringUtils.isBlank(token)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),iPropertyAppUserInfoServiceClient.getPropertyAppUserQRcode(projectId,userId));
        }catch (Exception e){
            throw new DataAccessException("【物业APP_通行模块】获取用户二维码失败",e);
        }
    }

    /**
     * <desc>
     *      物业APP云门禁iot开门
     * </desc>
     *
     * @param deviceUnique 设备序列号
     * @param token 用户凭证
     * @return
     * @author Juguang.S
     * @createDate 2020/01/03
     */
    @ResponseBody
    @RequestMapping("/netOpenDoor")
    public Object netOpenDoor(String deviceUnique,String correlationId,String token) throws Exception{
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            deviceUnique = request.getAttribute("deviceUnique") == null ? null : request.getAttribute("deviceUnique").toString();
            correlationId = request.getAttribute("correlationId") == null ? null : request.getAttribute("correlationId").toString();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            if(StringUtils.isEmpty(deviceUnique)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            //查询项目远程开门配置是否为启用 关闭则直接返回
            Integer networkOpen = iAppProjectServiceClient.getNetworkOpenSetting(StringHandlerUtil.getProjectIdByDeviceUnique(deviceUnique));
            if(DataStatusEnum.DELETE.getType()==networkOpen){
                return new MessageVO(AppErrorCodeEnum.CLOUD_ENTRANCE_NETWORK_OPEN_IS_CLOSED.getErrorCode());
            }
            //查询门禁设备的iot账号及绑定的iot产品key
            Map<String,Object> entrance = iCloudEntranceServiceClient.getMainDeviceUniqueAndProductKey(deviceUnique);
            Map<String,Object> result = new HashMap<>();
            if(entrance != null && entrance.get("deviceUnique") != null) {
                //判断当前设备是否在线，如不在线返回失败
                String isOnline = iIotServerServiceClient.batchGetDeviceState(entrance.get("productKey").toString(),entrance.get("deviceUnique").toString());
                if(isOnline == null || (isOnline != null && !isOnline.equals(IotDeviceStatusEnum.ONLINE.getType()))){
                    result.put("doorStatus",0);
                    return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),result);
                }
                iCloudEntranceServiceClient.entranceOpenOrCloseCtrl("itlong", entrance.get("deviceUnique").toString(),
                        Integer.valueOf(deviceUnique.substring(deviceUnique.length() - 4, deviceUnique.length())).toString(),
                        CloudEntranceOpenTypeEnum.OPEN.getType().toString(), "1", entrance.get("productKey").toString(), userId, correlationId,"0");
                //判断当前状态是否是开门，如果是开门则返回成功，否则返回失败
                int doorStatus = 2;
                int count = 0;
                while(count<10){
                    Thread.sleep(500);
                    IotCloudEntranceStateDTO dto = JsonUtil.toObject(redisService.getKeysForDevice(RedisConstant.REDIS_IOT_CLOUD_ENTRANCE_STATE_CACHE +
                            deviceUnique),IotCloudEntranceStateDTO.class);
                    if(dto != null && dto.getMsgCode() == 0){
                        doorStatus = 1;
                        break;
                    }
                    count++;
                }
                result.put("doorStatus", doorStatus);
            }else{
                result.put("doorStatus",0);
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),result);
        }catch (Exception e){
            throw new DataAccessException("【APP_首页版块】远程开门失败",e);
        }
    }

    /**
     * <desc>
     *      物业APP预约呼梯。
     * <desc/>
     *
     * @param  callLiftDTO 呼梯数据对象
     * @return
     * @author Juguang.S
     * @createDate 2020-01-03
     */
    @RequestMapping(value = "/cloudCallLift",method = RequestMethod.POST)
    @ResponseBody
    public Object callLift(AppCallLiftDTO callLiftDTO,String token) {
        MessageVO messageVO;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            callLiftDTO = HttpProtocolUtil.parseRequestParamToDTO(AppCallLiftDTO.class, request);
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            //判断设备唯一编号
            if (StringUtils.isBlank(callLiftDTO.getDeviceUnique())) {
                return new MessageVO(AppErrorCodeEnum.DEVICE_UNIQUE_EMPTY_ERR.getErrorCode());
            }
            String deviceUnique = callLiftDTO.getDeviceUnique();
            String projectId = deviceUnique.substring(0,8);
            String fromId = callLiftDTO.getFromId();
            String toId = callLiftDTO.getToId();
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            CloudElevatorVO vo = iAppDeviceServiceClient.getCallElevatorInfo(callLiftDTO.getDeviceUnique());
            //判断当前设备是否在线，如不在线返回失败
            String isOnline = iIotServerServiceClient.batchGetDeviceState(vo.getIotProductKey(),callLiftDTO.getDeviceUnique());
            if(isOnline ==null || (isOnline != null && !isOnline.equals(IotDeviceStatusEnum.ONLINE.getType()))){
                return new MessageVO(AppErrorCodeEnum.CLOUD_ELEVATOR_OUT_LINE.getErrorCode());
            }
            //查询电梯设备是否绑定控制器
            Map<String,Object> controller = iAppDeviceServiceClient.getControllerDeviceUniqueByElevatorDeviceUnique(callLiftDTO.getDeviceUnique());
            //判断群控器是否在线
            if(controller != null && controller.get("groupConId") != null){
                isOnline = iIotServerServiceClient.batchGetDeviceState(controller.get("iotProductKey").toString(),controller.get("groupConId").toString());
                if(isOnline ==null || (isOnline != null && !isOnline.equals(IotDeviceStatusEnum.ONLINE.getType()))){
                    return new MessageVO(AppErrorCodeEnum.CLOUD_ELEVATOR_OUT_LINE.getErrorCode());
                }
            }
            //判断楼层
            Map result = StringHandlerUtil.checkFloor(callLiftDTO.getFromId(), callLiftDTO.getToId(), PlatformConstants.MAX_FLOOR_NUM);
            if (!"0".equals(result.get("code").toString())) {
                return new MessageVO(AppErrorCodeEnum.ELEVATOR_FLOOR_ERROR.getErrorCode(), result.get("message"));
            }
            List<String> validFloor = new ArrayList<>(); //合法楼层
            List<String> liveFloorList = iPropertyAppUserInfoServiceClient.getLiveFloorByDeviceUnique(deviceUnique);
            if ((liveFloorList != null) && (liveFloorList.size() > 0)) {
                validFloor = liveFloorList.stream().filter(liveFloor -> (liveFloor.equals(fromId) || liveFloor.equals(toId))).collect(Collectors.toList());
            }
            if ((validFloor != null) && (validFloor.size() < 2)) {
                return new MessageVO(AppErrorCodeEnum.FLOOR_NOT_VALID_ERR.getErrorCode());
            }

            //取真实楼层
            AppElevatorFloorSimpleVO simpleVO = iAppHomeServiceClient.getRealFloorInfo(callLiftDTO.getDeviceUnique(), callLiftDTO.getFromId(), callLiftDTO.getToId());
            if (simpleVO == null) {
                LOG.info(String.format("【首页_预约呼梯】楼层号信息有误，设备号：%s 出发楼层：s%  目标楼层：s%", callLiftDTO.getDeviceUnique(), callLiftDTO.getFromId(), callLiftDTO.getToId()));
                return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode());
            }
            String snr = LogicIdUtil.randomNum();
            if(null != controller && null != controller.get("deviceUnique") ) {
                String userLabel = iAppDeviceServiceClient.getUserLabel(userId, StringHandlerUtil.getProjectIdByDeviceUnique(callLiftDTO.getDeviceUnique()));
                if(StringUtils.isBlank(userLabel) || !userLabel.contains("1")) {
                    Boolean isVipCall = iAppDeviceServiceClient.getIsVipCall(callLiftDTO.getDeviceUnique());
//                    LOG.info("是否处于vip呼梯中》》》》》》》》》》》》》》》》》》" + isVipCall);
                    if(isVipCall) {
                        return new MessageVO(BaseErrorCodeEnum.ELEVATOR_CALL_ERR.getErrorCode());
                    }
                }
            }
            //调用IOT呼梯
            iAppDeviceServiceClient.cloudElevatorCall(
                    callLiftDTO.getDeviceUnique(),
                    CloudElevatorSourceEnum.ITLONG_CLOUD_ELEVATOR.getDescription(),
                    simpleVO.getRealFrom(),simpleVO.getRealTo(),null, CloudElevatorCallTypeEnum.OUT.getType(),null,
                    CallElevatorSourceTypeEnum.APP.getType(),null,snr,null, null, null, userId, "");
            //装配呼梯记录对象
            AppCallLiftSaveDTO saveDTO = new AppCallLiftSaveDTO();
            saveDTO.setUserId(userId);
            if(controller != null && controller.get("groupConId") != null){
                saveDTO.setGroupConId(controller.get("groupConId").toString());
            }
            saveDTO.setDeviceUnique(callLiftDTO.getDeviceUnique());
            saveDTO.setFromFloor(callLiftDTO.getFromId());
            saveDTO.setToFloor(callLiftDTO.getToId());
            saveDTO.setProjectId(projectId);
            saveDTO.setSource(CallElevatorRecordSourceEnum.JIAR.getType());
            iAppHomeServiceClient.saveCallLiftRecord(saveDTO);
            Map<String, Object> returnData = new HashMap<>();
            returnData.put("deviceUnique", callLiftDTO.getDeviceUnique());
            returnData.put("fromId", callLiftDTO.getFromId());
            returnData.put("fromNum", simpleVO.getFromFloor());
            returnData.put("toId", callLiftDTO.getToId());
            returnData.put("toNum", simpleVO.getToFloor());
            messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), returnData);
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_通行版块】预约呼梯", e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      物业APP取消预约呼梯。
     * <desc/>
     *
     * @param  deviceUnique 设备唯一编码
     * @param  token 凭证
     * @return
     * @author Juguang.S
     * @createDate 2020-01-03
     */
    @RequestMapping(value = "/cancelCallLift",method = RequestMethod.POST)
    @ResponseBody
    public Object cancelCallLift(String deviceUnique,String token){
        MessageVO messageVO;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            deviceUnique = request.getAttribute("deviceUnique") == null ? null : request.getAttribute("deviceUnique").toString();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            //判断设备唯一编号
            if(StringUtils.isBlank(deviceUnique)){
                return new MessageVO(AppErrorCodeEnum.DEVICE_UNIQUE_EMPTY_ERR.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            String projectId = deviceUnique.substring(0,8);
            //取消预约呼梯
            iAppHomeServiceClient.cancelCallLift(userId,projectId,deviceUnique);

            messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        }catch (Exception e){
            throw new DataAccessException("【物业APP_通行版块】取消预约呼梯",e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      单楼层呼梯（内呼）
     * <desc/>
     *
     * @param token
     * @param deviceUnique
     * @param logicalFloor
     * @return
     * @author Juguang.S
     * @createDate 2020-04-14
     */
    @RequestMapping(value = "/inCall",method = RequestMethod.POST)
    @ResponseBody
    public Object inCall(String token,String deviceUnique,String logicalFloor,String language,String createTime,String sign) {
        try {
            HttpServletRequest request= ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
            token=request.getAttribute("token")==null?null:request.getAttribute("token").toString();
            deviceUnique=request.getAttribute("deviceUnique")==null?null:request.getAttribute("deviceUnique").toString();
            logicalFloor=request.getAttribute("logicalFloor")==null?null:request.getAttribute("logicalFloor").toString();
            createTime=request.getAttribute("createTime")==null?null:request.getAttribute("createTime").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            sign=request.getAttribute("sign")==null?null:request.getAttribute("sign").toString();
            if (StringUtils.isBlank(deviceUnique) || StringUtils.isBlank(logicalFloor)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            CloudElevatorVO vo = iAppDeviceServiceClient.getCallElevatorInfo(deviceUnique);
            //判断当前设备是否在线，如不在线返回失败
            String isOnline = iIotServerServiceClient.batchGetDeviceState(vo.getIotProductKey(),deviceUnique);
            if(isOnline ==null || (isOnline != null && !isOnline.equals(IotDeviceStatusEnum.ONLINE.getType()))){
                return new MessageVO(AppErrorCodeEnum.CLOUD_ELEVATOR_OPEN_ERROR.getErrorCode());
            }
            //获取真实楼层
            Map<String,Object> floor = iAppDeviceServiceClient.getFloorNumAndNaturalFloorByLogicFloor(logicalFloor,
                    deviceUnique);
            if(floor ==null || floor.get("floors") ==null || floor.get("naturals") == null){
                return new MessageVO(AppErrorCodeEnum.ELEVATOR_FLOOR_ERROR.getErrorCode());
            }
            AppUserCacheVO userInfoPo=(AppUserCacheVO)StringHandlerUtil.formatString(userCache.retrieve(token));
            //调用IOT呼梯
            iAppDeviceServiceClient.openOrAutoRegister(deviceUnique,
                    CloudElevatorSourceEnum.ITLONG_CLOUD_ELEVATOR.getDescription(),
                    floor.get("floors").toString(),  CloudElevatorCallTypeEnum.IN.getType(),0, CallElevatorSourceTypeEnum.MINIPROGRAM.getType(),null, userInfoPo.getUserId());

            //装配保存通行记录对象
            AppCallLiftSaveDTO saveDTO = new AppCallLiftSaveDTO();
            saveDTO.setUserId(userId);
            saveDTO.setDeviceUnique(deviceUnique);
            saveDTO.setProjectId(deviceUnique.substring(0,8));
            saveDTO.setMark(1);
            iAppHomeServiceClient.saveCallLiftRecord(saveDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业APP】单楼层呼梯", e);
        }
    }

    /**
     * <desc>
     *      物业APP获取呼梯记录。
     * <desc/>
     *
     * @param  token 凭证
     * @param deviceUnique 设备唯一ID
     * @return
     * @author Juguang.S
     * @createDate 2020-01-06
     */
    @RequestMapping(value = "/liftMark",method = RequestMethod.POST)
    @ResponseBody
    public Object getCallLiftRecord(String token,String deviceUnique){
        MessageVO messageVO;
        try{
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            deviceUnique = request.getAttribute("deviceUnique") == null ? null : request.getAttribute("deviceUnique").toString();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            List<AppCallElevatorRecordVO> recordVO = iAppHomeServiceClient.getCallElevatorRecord(userId,deviceUnique);
            messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),recordVO);
        }catch (Exception e){
            throw new DataAccessException("【物业APP_通行版块】获取呼梯记录失败",e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      物业APP删除呼梯记录。
     * <desc/>
     *
     * @param  token 凭证
     * @param  deviceUnique 设备唯一ID
     * @return
     * @author Juguang.S
     * @createDate 2020-01-06
     */
    @RequestMapping(value = "/deleteLiftMark",method = RequestMethod.POST)
    @ResponseBody
    public Object deleteCallLiftRecord(String token,String deviceUnique){
        MessageVO messageVO;
        try{
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            deviceUnique = request.getAttribute("deviceUnique") == null ? null : request.getAttribute("deviceUnique").toString();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            iAppHomeServiceClient.deleteCallElevatorRecord(userId,deviceUnique.substring(0,8),deviceUnique);
            messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        }catch (Exception e){
            throw new DataAccessException("【物业APP_通行版块】删除呼梯记录失败",e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      物业APP获取电梯时时状态。
     * <desc/>
     *
     * @param token 凭证
     * @param deviceUnique 设备唯一码列表
     * @return
     * @author Juguang.S
     * @createDate 2020-01-07
     */
    @RequestMapping(value = "/liftState",method = RequestMethod.POST)
    @ResponseBody
    public Object getElevatorOftenStatus(String token,String deviceUnique){
        MessageVO messageVO;
        try{
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            deviceUnique = request.getAttribute("deviceUnique") == null ? null : request.getAttribute("deviceUnique").toString();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            deviceUnique = URLDecoder.decode(deviceUnique, "UTF-8");
            //获取设备编号列表
            String[] deviceUniqueArr = StringHandlerUtil.splitString(deviceUnique);
            if((deviceUniqueArr==null)||(deviceUniqueArr.length<1)){
                return new MessageVO(AppErrorCodeEnum.DEVICE_UNIQUE_EMPTY_ERR.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            List<AppCloudElevatorRunState> eleRunStatesVO = iAppDeviceServiceClient.getCloudElevatorState(deviceUnique,userId);
            messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),eleRunStatesVO);
        }catch (Exception e){
            throw new DataAccessException("【物业APP_通行版块】获取电梯时时状态失败",e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      物业APP切换音视频
     * <desc/>
     *
     * @param videoState 0：音视频1音频
     * @param sipAccount sip帐号
     * @return
     * @author Juguang.S
     * @createDate 2020-01-08
     */
    @RequestMapping(value = "/switchVideo",method = RequestMethod.POST)
    @ResponseBody
    public Object switchVideo(String videoState, String sipAccount) {
        MessageVO messageVO;
        try {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                videoState = request.getAttribute("videoState") == null ? null : request.getAttribute("videoState").toString();
                sipAccount = request.getAttribute("sipAccount") == null ? null : request.getAttribute("sipAccount").toString();
            if (StringUtils.isBlank(sipAccount) || StringUtils.isBlank(videoState)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String deviceUnique = iCloudIntercomServiceClient.getDeviceUniqueBySip(sipAccount);
            //iot不在线走tcp
            if (redisService.get(RedisConstant.DEVICE_INTERCOM_IS_ONLINE_KEY+deviceUnique) == null ||
                    !redisService.get(RedisConstant.DEVICE_INTERCOM_IS_ONLINE_KEY+deviceUnique).equals("2")) {
//                messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),itcpServiceClient.sendMessage("",sipAccount,videoState, 11));
                return new MessageVO(AppErrorCodeEnum.CLOUD_TALK_IS_NOT_ONLINE_ERROR.getErrorCode());
            }else {//iot在线
                iCloudIntercomServiceClient.switchVideo(sipAccount,videoState);
                int count = 0;
                AppTCPResultVO appTCPResultVO = new AppTCPResultVO();
                appTCPResultVO.setDataFlag("1");
                appTCPResultVO.setVideoState("");
                while(count<10){
                    Thread.sleep(500);
                    IotCloudIntercomStateDTO dto = JsonUtil.toObject(redisService.getKeysForDevice(RedisConstant.REDIS_IOT_CLOUD_INTERCOM_STATE_CACHE +
                            deviceUnique),IotCloudIntercomStateDTO.class);
                    if(dto != null && dto.getMsgCode() == 0){
                        appTCPResultVO.setDataFlag("0");
                        appTCPResultVO.setVideoState(dto.getVideoState());
                        redisService.del(RedisConstant.REDIS_IOT_CLOUD_INTERCOM_STATE_CACHE +deviceUnique);
                        break;
                    }
                    count++;
                }
                messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),appTCPResultVO);
            }
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_通行版块】切换音视频失败", e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      物业APP用户云对讲开门操作
     * <desc/>
     *
     * @param sipAccount sip帐号
     * @param message 指令相关信息
     * @return
     * @author Juguang.S
     * @createDate 2020-01-08
     */
    @RequestMapping(value = "/cloudTalkOpen",method = RequestMethod.POST)
    @ResponseBody
    public Object appOpenDoor(String token,String sipAccount, String message) {
        MessageVO messageVO;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            sipAccount = request.getAttribute("sipAccount") == null ? null : request.getAttribute("sipAccount").toString();
            message = request.getAttribute("message") == null ? null : request.getAttribute("message").toString();
            if (StringUtils.isBlank(sipAccount) || StringUtils.isEmpty(message)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            String deviceUnique = iCloudIntercomServiceClient.getDeviceUniqueBySip(sipAccount);
            //iot不在线走tcp
            if (redisService.get(RedisConstant.DEVICE_INTERCOM_IS_ONLINE_KEY+deviceUnique) == null ||
                    !redisService.get(RedisConstant.DEVICE_INTERCOM_IS_ONLINE_KEY+deviceUnique).equals("2")) {
//                messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),itcpServiceClient.sendMessage(userId,sipAccount,message,10));
                return new MessageVO(AppErrorCodeEnum.CLOUD_TALK_IS_NOT_ONLINE_ERROR.getErrorCode());
            } else {//iot在线
                iCloudIntercomServiceClient.iotOpenDoor(userId,sipAccount,message,"1");
                int count = 0;
                AppTCPResultVO appTCPResultVO = new AppTCPResultVO();
                appTCPResultVO.setDataFlag("1");
                while(count<10){
                    Thread.sleep(500);
                    IotCloudIntercomStateDTO dto = JsonUtil.toObject(redisService.getKeysForDevice(RedisConstant.REDIS_IOT_CLOUD_INTERCOM_STATE_CACHE +
                            deviceUnique),IotCloudIntercomStateDTO.class);
                    if(dto != null && dto.getMsgCode() == 0){
                        appTCPResultVO.setDataFlag("0");
                        redisService.del(RedisConstant.REDIS_IOT_CLOUD_INTERCOM_STATE_CACHE +deviceUnique);
                        break;
                    }
                    count++;
                }
                messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),appTCPResultVO);
            }
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_通行版块】开门异常", e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      物业APP用户上传设备排序
     * <desc/>
     *
     * @param propertyAppDeviceInfoDTO 设备排序相关数据
     * @param token token
     * @return
     * @author Juguang.S
     * @createDate 2020-01-09
     */
    @ResponseBody
    @RequestMapping(value = "/upLoadAllSort",method = RequestMethod.POST)
    public Object upLoadAllSort(PropertyAppDeviceInfoDTO propertyAppDeviceInfoDTO, String token) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyAppDeviceInfoDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyAppDeviceInfoDTO.class, request);
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            String groupAry = request.getAttribute("groupAry") == null ? null : request.getAttribute("groupAry").toString();
            List<PropertyAppDeviceGroupInfoDTO> list = JSON.parseArray(groupAry, PropertyAppDeviceGroupInfoDTO.class);
            propertyAppDeviceInfoDTO.setGroupAry(list);
            if (propertyAppDeviceInfoDTO==null || StringUtils.isEmpty(propertyAppDeviceInfoDTO.getProjectId()) || StringUtils.isEmpty(propertyAppDeviceInfoDTO.getDeviceUniques())){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            propertyAppDeviceInfoDTO.setUserId(userId);
            Map<String,String> map = new HashMap<>();
            if(iPropertyAppUserInfoServiceClient.upLoadAllSort(propertyAppDeviceInfoDTO)>0){
                map.put("flag","1");
            }else{
                map.put("flag","0");
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),map);
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_通行版块】上传设备排序异常", e);
        }
    }

    /**
     * <desc>
     *      物业APP用户上传组设备排序
     * <desc/>
     *
     * @param propertyAppDeviceInfoDTO 组设备排序相关数据
     * @param token token
     * @return
     * @author Juguang.S
     * @createDate 2020-01-09
     */
    @ResponseBody
    @RequestMapping(value = "/deviceGroupSort",method = RequestMethod.POST)
    public Object deviceGroupSort(PropertyAppDeviceInfoDTO propertyAppDeviceInfoDTO, String token) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyAppDeviceInfoDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyAppDeviceInfoDTO.class, request);
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            if (propertyAppDeviceInfoDTO==null || StringUtils.isEmpty(propertyAppDeviceInfoDTO.getProjectId()) ||
                    StringUtils.isEmpty(propertyAppDeviceInfoDTO.getDeviceUniques()) || StringUtils.isEmpty(propertyAppDeviceInfoDTO.getGroupId())){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            propertyAppDeviceInfoDTO.setUserId(userId);
            propertyAppDeviceInfoDTO.setMark("3");
            Map<String,String> map = new HashMap<>();
            if(iPropertyAppUserInfoServiceClient.deviceGroupSort(propertyAppDeviceInfoDTO)>0){
                map.put("flag","1");
            }else{
                map.put("flag","0");
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),map);
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_通行版块】上传设备组排序异常", e);
        }
    }

    /**
     * <desc>
     *      物业APP用户设置分组名称
     * <desc/>
     *
     * @param propertyAppDeviceInfoDTO 组设备相关数据
     * @param token token
     * @return
     * @author Juguang.S
     * @createDate 2020-01-09
     */
    @ResponseBody
    @RequestMapping(value = "/setDeGroupName",method = RequestMethod.POST)
    public Object setDeGroupName(PropertyAppDeviceInfoDTO propertyAppDeviceInfoDTO, String token) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyAppDeviceInfoDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyAppDeviceInfoDTO.class, request);
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            if (propertyAppDeviceInfoDTO==null|| StringUtils.isEmpty(propertyAppDeviceInfoDTO.getProjectId()) ||
                    StringUtils.isEmpty(propertyAppDeviceInfoDTO.getName()) || StringUtils.isEmpty(propertyAppDeviceInfoDTO.getGroupId())){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            propertyAppDeviceInfoDTO.setUserId(userId);
            Map<String,String> map = new HashMap<>();
            if(iPropertyAppUserInfoServiceClient.setDeGroupName(propertyAppDeviceInfoDTO)>0){
                map.put("flag","1");
            }else{
                map.put("flag","0");
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),map);
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_通行版块】用户设置分组名称异常", e);
        }
    }

    /**
     * <desc>
     *      物业APP用户删除分组
     * <desc/>
     *
     * @param propertyAppDeviceInfoDTO 组设备相关数据
     * @param token token
     * @return
     * @author Juguang.S
     * @createDate 2020-01-09
     */
    @ResponseBody
    @RequestMapping(value = "/deleteDeviceGroup",method = RequestMethod.POST)
    public Object deleteDeviceGroup(PropertyAppDeviceInfoDTO propertyAppDeviceInfoDTO, String token) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyAppDeviceInfoDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyAppDeviceInfoDTO.class, request);
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            if (propertyAppDeviceInfoDTO==null || StringUtils.isEmpty(propertyAppDeviceInfoDTO.getGroupId())){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            propertyAppDeviceInfoDTO.setUserId(userId);
            propertyAppDeviceInfoDTO.setMark("1");
            Map<String,String> map = new HashMap<>();
            if(iPropertyAppUserInfoServiceClient.deviceGroupSort(propertyAppDeviceInfoDTO)>0){
                map.put("flag","1");
            }else{
                map.put("flag","0");
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),map);
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_通行版块】用户删除分组异常", e);
        }
    }

    /**
     * <desc>
     *      物业APP用户设备组增减设备
     * <desc/>
     *
     * @param propertyAppDeviceInfoDTO 组设备相关数据
     * @param token token
     * @return
     * @author Juguang.S
     * @createDate 2020-01-10
     */
    @ResponseBody
    @RequestMapping(value = "/changeGroupDevice",method = RequestMethod.POST)
    public Object changeGroupDevice(PropertyAppDeviceInfoDTO propertyAppDeviceInfoDTO, String token) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyAppDeviceInfoDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyAppDeviceInfoDTO.class, request);
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            if (propertyAppDeviceInfoDTO==null || StringUtils.isEmpty(propertyAppDeviceInfoDTO.getType()) || StringUtils.isEmpty(propertyAppDeviceInfoDTO.getProjectId()) ||
                    StringUtils.isEmpty(propertyAppDeviceInfoDTO.getChangeDevice())){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            propertyAppDeviceInfoDTO.setUserId(userId);
            propertyAppDeviceInfoDTO.setMark("2");
            Map<String,String> map = new HashMap<>();
            if(iPropertyAppUserInfoServiceClient.deviceGroupSort(propertyAppDeviceInfoDTO)>0){
                map.put("flag","1");
            }else{
                map.put("flag","0");
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),map);
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_通行版块】物业APP用户设备组增减设备异常", e);
        }
    }

    /**
     * <desc>
     *      物业APP用户获取设备列表
     * <desc/>
     *
     * @param propertyAppDeviceInfoDTO 组设备相关数据
     * @param token token
     * @return
     * @author Juguang.S
     * @createDate 2020-01-13
     */
    @ResponseBody
    @RequestMapping(value = "/getDeviceList",method = RequestMethod.POST)
    public Object getDeviceList(PropertyAppDeviceInfoDTO propertyAppDeviceInfoDTO, String token) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyAppDeviceInfoDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyAppDeviceInfoDTO.class, request);
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            if (propertyAppDeviceInfoDTO==null || StringUtils.isEmpty(propertyAppDeviceInfoDTO.getProjectId())){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,propertyAppUserTokenKey);
            propertyAppDeviceInfoDTO.setUserId(userId);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),iPropertyAppDeviceInfoServiceClient.getDeviceList(propertyAppDeviceInfoDTO));
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_通行版块】物业APP用户获取设备列表异常", e);
        }
    }

    /**
     * <desc>
     *      上传通行记录
     * </desc>
     *
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2020/02/17
     */
    @RequestMapping(path = "/upLoadPassRecord", method = RequestMethod.POST)
    @ResponseBody
    public Object upLoadPassRecord(HttpServletRequest request){
        MessageVO messageVO;
        try {
            PropertyAppDeviceInfoDTO propertyAppDeviceInfoDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyAppDeviceInfoDTO.class, request);
            if (propertyAppDeviceInfoDTO == null || StringUtils.isBlank(propertyAppDeviceInfoDTO.getProjectId()) || StringUtils.isBlank(propertyAppDeviceInfoDTO.getRecordJson())
                    || StringUtils.isBlank(propertyAppDeviceInfoDTO.getToken())) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String projectId = propertyAppDeviceInfoDTO.getProjectId();
            String recordJson = URLDecoder.decode(propertyAppDeviceInfoDTO.getRecordJson(), "UTF-8");
            try {
                JsonUtil.decode(recordJson, new TypeReference<List<AppUploadRecordJsonDTO>>() {});
            } catch (IOException e) {
                return new MessageVO(BaseErrorCodeEnum.PARAM_ERR.getErrorCode());
            }
            if(StringUtils.isBlank(propertyAppDeviceInfoDTO.getImageStr()) && StringUtils.isBlank(propertyAppDeviceInfoDTO.getImageType())){
                propertyAppDeviceInfoDTO.setImageStr("");
                propertyAppDeviceInfoDTO.setImageType("");
            }
            // 设置数据上限
            List<AppUploadRecordJsonDTO> dtos = JsonUtil.decode(recordJson, new TypeReference<List<AppUploadRecordJsonDTO>>() {});
            if (dtos == null || dtos.size() >= 100) {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }
            // 从缓存中获取用户信息
            PropertyUserCacheVO userCacheVO = iPropertyAppUserInfoServiceClient.retrieve(propertyAppDeviceInfoDTO.getToken());

            // 预留对于太多数据上传的多线程处理
//            new Thread(() -> {
//                try {
//                    List<AppUploadPassErrorVO> list = iAppDevicePassRecordServiceClient.uploadRecord(userCacheVO.getUserId(), projectId, recordJson,
//                            propertyAppDeviceInfoDTO.getImageStr(), propertyAppDeviceInfoDTO.getImageType());
//                } catch (Exception e) {
//                }
//            }
//            ).start();

            // 上传数据，返回未上传成功的数据
            List<AppUploadPassErrorVO> list = iAppDevicePassRecordServiceClient.uploadRecord(userCacheVO.getUserId(), projectId, recordJson,
                    propertyAppDeviceInfoDTO.getImageStr(), propertyAppDeviceInfoDTO.getImageType());
            if (null == list || list.isEmpty()) {
                messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            } else {
                Map<String, Object> result = new HashMap<>();
                list.forEach(vo -> vo = (AppUploadPassErrorVO) StringHandlerUtil.formatString(vo));
                result.put("failrecordlist", list);
                messageVO = new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(), result);
            }

        }catch (Exception e){
            throw new DataAccessException("【物业APP_通行版块】物业APP上传用户通行记录异常", e);
        }
        return messageVO;
    }

}
